﻿//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//    FrequencyCounter.cs
//
// Abstract:
//    
//    Helper class to count the frequency of an integer variable.
//
//    Note: THIS CODE IS NOT TO BE SHIPPED.
//
//--

using System;
using System.Diagnostics;
using System.IO;

namespace Microsoft.EnhancedRemindersTools
{
    internal sealed class FrequencyCounter
    {
        private readonly uint[] _frequencyCounter;
        private uint? _overflowBin;

        /// <summary>
        /// Ctor.
        /// </summary>
        /// <param name="maxFrequency">Frequencies are counted over the range 0..maxFrequency-1.</param>
        /// <param name="useOverflow">True to track the frequency of values >= maxFrequency; false otherwise.</param>
        internal FrequencyCounter(uint maxFrequency, bool useOverflow)
        {
            _frequencyCounter = new uint[maxFrequency];

            if (useOverflow)
            {
                _overflowBin = 0;
            }
        }

        /// <summary>
        /// Update the frequency count for a variable.
        /// </summary>
        /// <param name="value">The variable to update.</param>
        internal void Update(uint value)
        {
            if (value < _frequencyCounter.Length)
            {
                ++_frequencyCounter[value];
            }
            else if (_overflowBin != null)
            {
                ++_overflowBin;
            }
        }

        /// <summary>
        /// Outputs the summary line for the variables frequencies.
        /// </summary>
        /// <param name="summaryFile">The file to write to.</param>
        /// <param name="header">Description of the variable.</param>
        /// <param name="itemFormat">Formats string for writing each frequency, e.g. "foo: {0} = bar {1}"</param>
        internal void WriteSummary(StreamWriter summaryFile, string header, string itemFormat)
        {
            Debug.Assert(summaryFile != null, "summaryFile");
            Debug.Assert(!String.IsNullOrEmpty(header), "header");
            Debug.Assert(!String.IsNullOrEmpty(itemFormat), "itemFormat");
            Debug.Assert(itemFormat.Contains("{0}"), "itemFormat contains {0}");
            Debug.Assert(itemFormat.Contains("{1}"), "itemFormat contains {1}");

            summaryFile.Write(header);

            for (uint i = 0; i < _frequencyCounter.Length; i++)
            {
                if (i > 0)
                {
                    summaryFile.Write(',');
                }
                summaryFile.Write(itemFormat, i, _frequencyCounter[i]);
            }

            if (_overflowBin.HasValue)
            {
                summaryFile.Write(',');
                summaryFile.Write("items greater than {0}: {1}", _frequencyCounter.Length - 1, _overflowBin.Value);
            }

            summaryFile.WriteLine();
        }
    }
}